﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufExtension.h"
#include <GnufPallet.h>
#include "GnufQtObjectPtr.h"

namespace gcmp { class IModelView; }

namespace gnuf {

    class QtBnufLinkFilter;

    class GNUF_EXTENSION_EXPORT GnufFilterItem final : public gcmp::WeakReferenceable
    {
        CANNOT_COPY_OR_ASSIGN(GnufFilterItem)
    public:
        GnufFilterItem();
        GnufFilterItem(const std::wstring & category, const std::wstring & filterName, const std::wstring & filterCode);
        ~GnufFilterItem();
        bool operator<(const GnufFilterItem &) const;
        void addChild(gcmp::OwnerPtr<GnufFilterItem>);
        const std::vector<gcmp::WeakPtr<GnufFilterItem>>& children() const { return m_children; }

        std::list<std::wstring> checkedCategories() const;

        void setChecked(bool);
        bool isChecked() const;
        void setCheckedInitially(bool isCheckedInitial) { m_checkedInitially = isCheckedInitial; }
        bool isCheckedInitially() const { return m_checkedInitially; }

        // Set if checked initially.
        enum class ECheckState:std::uint8_t
        { eUnchecked = 0, ePartiallyChecked = 1, eChecked = 2 };
        GnufFilterItem::ECheckState initialCheckState() const;
        
        std::wstring getCategory() const { return m_category; }
        void setCategory(const std::wstring& category) { m_category = category; }
        std::wstring getfilterName() const { return m_filterName; }
        void setfilterName(const std::wstring& filterName) { m_filterName = filterName; }
        std::wstring getfilterCode() const { return m_filterCode; }
        void setfilterCode(const std::wstring& filterCode) { m_filterCode = filterCode; }

    private:
        friend class QtBnufFilterItem;
        void    connectWith(QtBnufFilterItem *);
        void disconnectFrom(const QtBnufFilterItem * const);

        QtBnufFilterItem * m_qtImpl;
        std::wstring m_category;
        std::wstring m_filterName;
        std::wstring m_filterCode;
        std::vector<gcmp::WeakPtr<GnufFilterItem>> m_children;

        bool m_checkedInitially = false;
    };

    class GNUF_EXTENSION_EXPORT GnufLinkFilter final
        : public IPalletEventHandler
    {
        CANNOT_COPY_OR_ASSIGN(GnufLinkFilter)
    public:
        explicit GnufLinkFilter(
            const std::wstring & title, 
            const std::wstring & banner,
            const std::wstring & warning);
        ~GnufLinkFilter();

        void addGroup(gcmp::OwnerPtr<GnufFilterItem> group);

        std::vector<gcmp::WeakPtr<GnufFilterItem>> items() const { return m_items; }
        std::vector< GnufFilterItem * > rawItems();

        // Show.
        enum EResultCode {
            eSubmit,
            eCancel
        };
        EResultCode show();

        std::vector<std::wstring> getSelectedCodes() const;

    protected:
        // Inherits from IPalletEventHandler...
        virtual void onHeaderButtonClicked(Pallet *) override;
        virtual bool onFooterButtonClicked(Pallet *) override;
        virtual bool onKeyEvent(Pallet *, IPalletEventHandler::EKey) override;
        virtual void onContentChanged(Pallet *) override;

    private:
        std::vector<gcmp::WeakPtr<GnufFilterItem>> m_items;
        gcmp::QtAutoPtr<QtBnufLinkFilter> m_qtLinkFilter;
        const std::wstring m_title;
        GnufLinkFilter::EResultCode m_resultCode;
    };
}
